#include "CellChecker.h"

bool CellChecker::Check (const Point& p, Condition idx)
{
	switch (idx)
	{
	case SAFE:
		{
			return IsSafe (p);
		}
	case PATROL:
		{
			return AllIsSeen (p);
		}
	case UNBLOCK:
		{
			return NotInPath (p);
		}
	case MY_SHOOTING_RANGE:
		{
			return InMyRange (p);
		}
	case ENEMY_VISION_RANGE:
		{
			return InEnemyRange (p);
		}
	case THROW:
		{
			return GrenadeReachable (p);
		}
	}
}

bool CloseEnough (const Point& p1, const Point& p2, int radius)
{
	return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) <= radius * radius;
}

bool CellChecker::GrenadeReachable (const Point& p)
{
	for (size_t i = 0; i < cellThrowGrenageInfo.enemies.size (); ++i)
	{
		Trooper& enemy = cellThrowGrenageInfo.enemies[i];

		if (enemy.getDistanceTo (p.x, p.y) <= cellThrowGrenageInfo.pgame->getGrenadeThrowRange () ||
			CloseEnough (Point (enemy.getX () - 1, enemy.getY ()), p, cellThrowGrenageInfo.pgame->getGrenadeThrowRange ()) ||
			CloseEnough (Point (enemy.getX (), enemy.getY () - 1), p, cellThrowGrenageInfo.pgame->getGrenadeThrowRange ()) ||
			CloseEnough (Point (enemy.getX () + 1, enemy.getY ()), p, cellThrowGrenageInfo.pgame->getGrenadeThrowRange ()) ||
			CloseEnough (Point (enemy.getX (), enemy.getY () + 1), p, cellThrowGrenageInfo.pgame->getGrenadeThrowRange ()))
		{
			return true;
		}
	}
	return false;
}

bool CellChecker::InMyRange (const Point& p)
{
	return cellMyShootingRangeInfo.pworld->isVisible (cellMyShootingRangeInfo.myShootingRange, p.x, p.y, STANDING, cellMyShootingRangeInfo.enemyLocation.x, cellMyShootingRangeInfo.enemyLocation.y, STANDING);
}

bool CellChecker::InEnemyRange (const Point& p)
{
	return cellEnemyVisionRangeInfo.pworld->isVisible (cellEnemyVisionRangeInfo.enemyVisionRange, cellEnemyVisionRangeInfo.enemyLocation.x, cellEnemyVisionRangeInfo.enemyLocation.y, STANDING, p.x, p.y, STANDING);
}

bool CellChecker::NotInPath (const Point& p)
{
	for (size_t i = 0; i < cellPathUnblockInfo.pathToUnblock.size (); ++i)
	{
		if (cellPathUnblockInfo.pathToUnblock[i] == p) return false;
	}
	return true;
}

bool CellChecker::IsSafe (const Point& p)
{
	for (size_t i = 0; i < cellSafeInfo.lookers.size (); ++i)
	{
		Trooper& looker = cellSafeInfo.lookers[i];
		if (cellSafeInfo.pworld->isVisible (looker.getVisionRange (), looker.getX (), looker.getY (), looker.getStance (),
			p.x, p.y, cellSafeInfo.cellStance))
		{
			return false;
		}
	}

	return true;
}

bool CellChecker::AllIsSeen (const Point& p)
{
	for (int i = cellPatrolInfo.cellsToSee.size () - 1; i >= 0; --i)
	{
		if (cellPatrolInfo.pworld->isVisible (cellPatrolInfo.range, p.x, p.y, STANDING, cellPatrolInfo.cellsToSee[i].x, cellPatrolInfo.cellsToSee[i].y, STANDING))
		{
			cellPatrolInfo.cellsToSee.erase (cellPatrolInfo.cellsToSee.begin () + i);
		}
	}

	return cellPatrolInfo.cellsToSee.empty ();
}